Skip to content

Commit 2325912

Browse files
Handle boundaries in multipart request
(cherry picked from commit 515a271)
1 parent 7236f9c commit 2325912

File tree

4 files changed

+141
-87
lines changed

4 files changed

+141
-87
lines changed

common/src/main/java/com/genexus/CommonUtil.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
import java.math.BigDecimal;
1010
import java.io.*;
1111
import java.net.URLEncoder;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
14+
import java.nio.file.Paths;
1215
import java.text.*;
1316
import java.util.*;
1417

@@ -176,6 +179,62 @@ public Object initialValue()
176179
throw new ExceptionInInitializerError("GXUtil static constructor error: " + e.getMessage());
177180
}
178181
}
182+
183+
public static String getContentType(String fileName) {
184+
Path path = Paths.get(fileName);
185+
String defaultContentType = "application/octet-stream";
186+
187+
try {
188+
String probedContentType = Files.probeContentType(path);
189+
if (probedContentType == null || probedContentType.equals(defaultContentType))
190+
return findContentTypeByExtension(fileName);
191+
return probedContentType;
192+
} catch (IOException ioe) {
193+
return findContentTypeByExtension(fileName);
194+
}
195+
}
196+
197+
private static String findContentTypeByExtension(String fileName) {
198+
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
199+
String contentType = contentTypes.get(fileExtension);
200+
return contentType != null ? contentTypes.get(fileExtension) : "application/octet-stream";
201+
}
202+
203+
private static Map<String, String> contentTypes = new HashMap<String, String>() {{
204+
put("txt" , "text/plain");
205+
put("rtx" , "text/richtext");
206+
put("htm" , "text/html");
207+
put("html" , "text/html");
208+
put("xml" , "text/xml");
209+
put("aif" , "audio/x-aiff");
210+
put("au" , "audio/basic");
211+
put("wav" , "audio/wav");
212+
put("bmp" , "image/bmp");
213+
put("gif" , "image/gif");
214+
put("jpe" , "image/jpeg");
215+
put("jpeg" , "image/jpeg");
216+
put("jpg" , "image/jpeg");
217+
put("jfif" , "image/pjpeg");
218+
put("tif" , "image/tiff");
219+
put("tiff" , "image/tiff");
220+
put("png" , "image/x-png");
221+
put("3gp" , "video/3gpp");
222+
put("3g2" , "video/3gpp2");
223+
put("mpg" , "video/mpeg");
224+
put("mpeg" , "video/mpeg");
225+
put("mov" , "video/quicktime");
226+
put("qt" , "video/quicktime");
227+
put("avi" , "video/x-msvideo");
228+
put("exe" , "application/octet-stream");
229+
put("dll" , "application/x-msdownload");
230+
put("ps" , "application/postscript");
231+
put("pdf" , "application/pdf");
232+
put("svg" , "image/svg+xml");
233+
put("tgz" , "application/x-compressed");
234+
put("zip" , "application/x-zip-compressed");
235+
put("gz" , "application/x-gzip");
236+
put("json" , "application/json");
237+
}};
179238

180239
public static String removeAllQuotes(String fileName)
181240
{

common/src/main/java/com/genexus/internet/GXHttpClient.java

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -567,74 +567,81 @@ protected String setPathUrl(String url) {
567567
return url;
568568
}
569569

570+
571+
protected File fileToPost;
572+
protected String fileToPostName;
573+
570574
@SuppressWarnings("unchecked")
571575
protected byte[] getData()
572576
{
573577
byte[] out = new byte[0];
574578

575-
for (Object key: getVariablesToSend().keySet())
579+
for (Object key : getVariablesToSend().keySet())
576580
{
577-
String value = getMultipartTemplate().getFormDataTemplate((String)key, (String)getVariablesToSend().get(key));
578-
getContentToSend().add(0, value); //Variables al principio
581+
String value = getMultipartTemplate().getFormDataTemplate((String) key, (String) getVariablesToSend().get(key));
582+
getContentToSend().add(0, value); // Variables al principio
579583
}
580584

581585
for (int idx = 0; idx < getContentToSend().size(); idx++)
582586
{
583587
Object curr = getContentToSend().elementAt(idx);
584588

585-
if (curr instanceof String)
589+
if (curr instanceof String)
586590
{
587591
try
588592
{
589-
if(contentEncoding != null)
593+
if (contentEncoding != null)
590594
{
591-
out = addToArray(out, ((String)curr).getBytes(contentEncoding));
592-
}else
595+
out = addToArray(out, ((String) curr).getBytes(contentEncoding));
596+
} else
593597
{
594598
out = addToArray(out, (String) curr);
595599
}
596-
}catch(UnsupportedEncodingException e)
600+
} catch (UnsupportedEncodingException e)
597601
{
598602
System.err.println(e.toString());
599603
out = addToArray(out, (String) curr);
600604
}
601605
}
602-
else if (curr instanceof Object[])
606+
else if (curr instanceof Object[])
603607
{
604-
StringWriter writer = (StringWriter)((Object[])curr)[0];
605-
StringBuffer encoding = (StringBuffer)((Object[])curr)[1];
608+
StringWriter writer = (StringWriter) ((Object[]) curr)[0];
609+
StringBuffer encoding = (StringBuffer) ((Object[]) curr)[1];
606610

607-
if(encoding == null || encoding.length() == 0)
611+
if (encoding == null || encoding.length() == 0)
608612
{
609613
encoding = new StringBuffer("UTF-8");
610614
}
611615
try
612616
{
613617
out = addToArray(out, writer.toString().getBytes(encoding.toString()));
614618
}
615-
catch(UnsupportedEncodingException e)
619+
catch (UnsupportedEncodingException e)
616620
{
617621
out = addToArray(out, writer.toString());
618622
}
619623
}
620-
else if (curr instanceof byte[])
624+
else if (curr instanceof byte[])
621625
{
622626
out = addToArray(out, (byte[]) curr);
623627
}
624-
else //File or FormFile
628+
else // File or FormFile
625629
{
626630
File file;
627631
if (curr instanceof FormFile)
628632
{
629-
FormFile formFile = (FormFile)curr;
633+
FormFile formFile = (FormFile) curr;
630634
out = startMultipartFile(out, formFile.name, formFile.file);
631635
file = new File(formFile.file);
636+
fileToPostName = formFile.name;
632637
}
633638
else
634639
{
635640
file = (File) curr;
636641
}
637-
try (BufferedInputStream bis = new java.io.BufferedInputStream(new FileInputStream(file)))
642+
fileToPost = file;
643+
644+
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)))
638645
{
639646
out = addToArray(out, CommonUtil.readToByteArray(bis));
640647
}

gxcloudstorage-awss3-v2/src/main/java/com/genexus/db/driver/ExternalProviderS3V2.java

Lines changed: 3 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.apache.logging.log4j.Logger;
1818
import org.apache.logging.log4j.LogManager;
1919

20+
import com.genexus.CommonUtil;
2021
import com.genexus.util.GXService;
2122
import com.genexus.util.StorageUtils;
2223
import com.genexus.StructSdtMessages_Message;
@@ -292,62 +293,6 @@ public String copy(String objectUrl, String newName, String tableName, String fi
292293
copyWithoutACL(objectUrl, newName, tableName, fieldName);
293294
}
294295

295-
private String getContentType(String fileName) {
296-
Path path = Paths.get(fileName);
297-
String defaultContentType = "application/octet-stream";
298-
299-
try {
300-
String probedContentType = Files.probeContentType(path);
301-
if (probedContentType == null || probedContentType.equals(defaultContentType))
302-
return findContentTypeByExtension(fileName);
303-
return probedContentType;
304-
} catch (IOException ioe) {
305-
return findContentTypeByExtension(fileName);
306-
}
307-
}
308-
309-
private String findContentTypeByExtension(String fileName) {
310-
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
311-
String contentType = contentTypes.get(fileExtension);
312-
return contentType != null ? contentTypes.get(fileExtension) : "application/octet-stream";
313-
}
314-
315-
private static Map<String, String> contentTypes = new HashMap<String, String>() {{
316-
put("txt" , "text/plain");
317-
put("rtx" , "text/richtext");
318-
put("htm" , "text/html");
319-
put("html" , "text/html");
320-
put("xml" , "text/xml");
321-
put("aif" , "audio/x-aiff");
322-
put("au" , "audio/basic");
323-
put("wav" , "audio/wav");
324-
put("bmp" , "image/bmp");
325-
put("gif" , "image/gif");
326-
put("jpe" , "image/jpeg");
327-
put("jpeg" , "image/jpeg");
328-
put("jpg" , "image/jpeg");
329-
put("jfif" , "image/pjpeg");
330-
put("tif" , "image/tiff");
331-
put("tiff" , "image/tiff");
332-
put("png" , "image/x-png");
333-
put("3gp" , "video/3gpp");
334-
put("3g2" , "video/3gpp2");
335-
put("mpg" , "video/mpeg");
336-
put("mpeg" , "video/mpeg");
337-
put("mov" , "video/quicktime");
338-
put("qt" , "video/quicktime");
339-
put("avi" , "video/x-msvideo");
340-
put("exe" , "application/octet-stream");
341-
put("dll" , "application/x-msdownload");
342-
put("ps" , "application/postscript");
343-
put("pdf" , "application/pdf");
344-
put("svg" , "image/svg+xml");
345-
put("tgz" , "application/x-compressed");
346-
put("zip" , "application/x-zip-compressed");
347-
put("gz" , "application/x-gzip");
348-
put("json" , "application/json");
349-
}};
350-
351296
private String buildPath(String... pathPart) {
352297
ArrayList<String> pathParts = new ArrayList<>();
353298
for (String part : pathPart) {
@@ -701,7 +646,7 @@ private String copyWithACL(String objectUrl, String newName, String tableName, S
701646
.bucket(bucket)
702647
.key(resourceKey)
703648
.metadata(metadata)
704-
.contentType(getContentType(newName));
649+
.contentType(CommonUtil.getContentType(newName));
705650
if (endpointUrl.contains(".amazonaws.com"))
706651
putObjectRequestBuilder = putObjectRequestBuilder.acl(internalToAWSACLWithACL(acl));
707652
PutObjectRequest putObjectRequest = putObjectRequestBuilder.build();
@@ -821,7 +766,7 @@ private String copyWithoutACL(String objectUrl, String newName, String tableName
821766
.bucket(bucket)
822767
.key(resourceKey)
823768
.metadata(metadata)
824-
.contentType(getContentType(newName));
769+
.contentType(CommonUtil.getContentType(newName));
825770
PutObjectRequest putObjectRequest = putObjectRequestBuilder.build();
826771
client.putObject(putObjectRequest, RequestBody.fromBytes(objectBytes.asByteArray()));
827772

java/src/main/java/com/genexus/internet/HttpClientJavaLib.java

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -495,24 +495,67 @@ public void execute(String method, String url) {
495495
HttpPost httpPost = new HttpPost(url.trim());
496496
httpPost.setConfig(reqConfig);
497497
Set<String> keys = getheadersToSend().keySet();
498-
boolean hasConentType = false;
498+
boolean hasContentType = false;
499+
499500
for (String header : keys) {
500501
httpPost.addHeader(header, getheadersToSend().get(header));
501-
if (header.equalsIgnoreCase("Content-type"))
502-
hasConentType = true;
502+
if (header.equalsIgnoreCase("Content-Type")) {
503+
hasContentType = true;
504+
}
503505
}
504-
if (!hasConentType) // Si no se setea Content-type, se pone uno default
505-
httpPost.addHeader("Content-type", "application/x-www-form-urlencoded");
506506

507-
ByteArrayEntity dataToSend;
508-
if (!getIsMultipart() && getVariablesToSend().size() > 0)
509-
dataToSend = new ByteArrayEntity(com.genexus.CommonUtil.hashtable2query(getVariablesToSend()).getBytes());
510-
else
511-
dataToSend = new ByteArrayEntity(getData());
512-
httpPost.setEntity(dataToSend);
507+
if (getIsMultipart()) {
508+
if (!hasContentType) {
509+
httpPost.addHeader("Content-Type", "multipart/form-data");
510+
}
513511

514-
response = httpClient.execute(httpPost, httpClientContext);
512+
String boundary = "----Boundary" + System.currentTimeMillis();
513+
httpPost.removeHeaders("Content-Type");
514+
httpPost.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
515515

516+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
517+
518+
for (Map.Entry<String, String> entry : ((Map<String, String>) getVariablesToSend()).entrySet()) {
519+
if ("fileFieldName".equals(entry.getKey())) {
520+
continue;
521+
}
522+
bos.write(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8));
523+
bos.write(("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n").getBytes(StandardCharsets.UTF_8));
524+
bos.write(entry.getValue().getBytes(StandardCharsets.UTF_8));
525+
bos.write("\r\n".getBytes(StandardCharsets.UTF_8));
526+
}
527+
if (getData() != null && getData().length > 0) {
528+
String fileFieldName = getVariablesToSend().containsKey("fileFieldName") ?
529+
(String) getVariablesToSend().get("fileFieldName") : fileToPostName;
530+
String fileName = fileToPost != null ? fileToPost.getName() : "uploadedFile";
531+
String contentType = fileToPost != null ? CommonUtil.getContentType(fileName) : "application/octet-stream";
532+
533+
bos.write(("--" + boundary + "\r\n").getBytes(StandardCharsets.UTF_8));
534+
bos.write(("Content-Disposition: form-data; name=\"" + fileFieldName + "\"; filename=\"" + fileName + "\"\r\n").getBytes(StandardCharsets.UTF_8));
535+
bos.write(("Content-Type: " + contentType + "\r\n\r\n").getBytes(StandardCharsets.UTF_8));
536+
bos.write(getData());
537+
bos.write("\r\n".getBytes(StandardCharsets.UTF_8));
538+
}
539+
540+
bos.write(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8));
541+
ByteArrayEntity dataToSend = new ByteArrayEntity(bos.toByteArray());
542+
httpPost.setEntity(dataToSend);
543+
} else {
544+
if (!hasContentType) {
545+
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
546+
}
547+
548+
ByteArrayEntity dataToSend;
549+
if (getVariablesToSend().size() > 0) {
550+
String formData = CommonUtil.hashtable2query(getVariablesToSend());
551+
dataToSend = new ByteArrayEntity(formData.getBytes(StandardCharsets.UTF_8));
552+
} else {
553+
dataToSend = new ByteArrayEntity(getData());
554+
}
555+
httpPost.setEntity(dataToSend);
556+
}
557+
558+
response = httpClient.execute(httpPost, httpClientContext);
516559
} else if (method.equalsIgnoreCase("PUT")) {
517560
HttpPut httpPut = new HttpPut(url.trim());
518561
httpPut.setConfig(reqConfig);

0 commit comments

Comments
 (0)