Laravel - Import File Using Octet-Stream - php

I was curious if anyone has ever imported a file where the post parameters in the developer bar is formatted like below with the content-type being application/octet-stream?
Below is just the first couple of lines of the parameters sent in the post data:
-----------------------------24464570528145
Content-Disposition: form-data; name="RemoteFile"; filename="594.pdf"
Content-Type: application/octet-stream
%PDF-1.5
1 0 obj
<<
/Creator ()
/CreationDate (2
I'm curious how I would upload the file through the model controller and I'm hoping someone else here might have run across this sort of issue.

Just use this one line of code
(new FileSystem)->put('/path/to/file.txt', $request->getContent());

Related

How can I go about converting binary ASCII received as a HTTP response into to a zip file

I'm having an issue trying to read data from a HTTP POST request that has multiple attachments with mime boundaries like so :
----MIME_boundary
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: 8bit
Content-Id: <xml.xml>
xml data
----MIME_boundary
Content-Type: application/zip
Content-Transfer-Encoding: binary
Content-Disposition: attachment; filename="test.zip"
Content-Id: <test.zip>
PK (binary/ASCII data)
----MIME_boundary--
I have split the request up into the data I need using a function wrote with help from this post : Manually parse raw multipart/form-data data with PHP
Essentially, I have been able to take the binary of that zip file, and then feed it to another function I have written, which should be able to create a temporary zip file from the binary, that I can then use the ZipArchive class in PHP to read and return a list of all the files within that zip file.
public static function unzip($zipBinary) {
$zip = new ZipArchive;
// create temp file from given binary
$file = tempnam("tmp", "zip");
file_put_contents($file, $zipBinary);
$res = $zip->open($file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE);
if ($res === TRUE) {
$files = [];
// create array of files from zip
for ($i = 0; $i < $zip->numFiles; $i++) {
$files[$zip->getNameIndex($i)] = $zip->getFromIndex($i);
}
$zip->close();
// delete temp file
unlink($file);
return $files;
}
}
The issue I've been having and can't seem to solve for the life of me is that the zip file created using file_put_contents seems to not work at all. When I try to count the number of files, I get 0. I am not sure if this is a problem with the binary in the example request that I have been given to set up the REST endpoint, or if it's an issue with my code.
I have tried a few different forms of debugging - I've tested that the zip file is actually being populated by looking at the return value of file_put_contents(), and I've also tried using rename() on the temporary file to put it in the same directory as my script to see if the zip file is valid and can be opened - which it is not, I get 'unsupported format' errors when trying to open it - I have also tried opening it with a text editor to no avail. I will probably try converting a different zip file to binary and trying to see if I encounter the same issues after I have finished posting this.
I would be extremely grateful if anyone could point me in the right direction and let me know if it's a problem with the binary (and how I could possibly solve it), or whether I can make code changes to alleviate the issue.
I have tried many different things from many different google/stackoverflow searches with no success, and thought that I would post here as a last resort.
Thanks

Multipart PUT in PHP (data and files)

I have been tasked with building the API for an existing mobile app. App is sending multipart data and files in the same PUT request. As an example, there is /api/employee/personal-info PUT endpoint (notice no ID in the URI) which is a multipart - JSON data and 2 images.
PHP does not have native support for PUT, it doesn't nicely put everything in $_FILES and $_POST so I have to decode the input manually.
I first have to do file_get_contents("php://input") which gives me the raw data. I have to use regex to extract the boundary string, then I need to split the input into blocks using that boundary (and regex again) and then decide whether the block is JSON or a file, by looking at Content-Disposition on each of the blocks. If it is a file, I have to regex out the filename and extension, and populate $_FILES array manually.
Json bloks have those headers (inside the body, just before the actual data)
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=model
and file blocks only have this:
Content-Disposition: form-data; name=file; filename=IMG_20180208_1.jpg; filename*=utf-8’’IMG_20180208_1.jpg
So the Content-Disposition of the whole input is multipart/form-data but then each of the blocks have their own headers, depending whether it is a file or JSON data.
Is this really the only way to do it in PHP?
Should the PUT endpoints NOT be multipart as a rule when it comes to PHP?
Am I missing something?

HTTP Post Upload Multiple Files from iOS to PHP

In my iOS app, I'm building an NSData to use as the body for an NSMutableURLRequest so that I can upload multiple files in one HTTP POST.
The contents of my post body look like this (with the file data removed and just replaced with the byte count):
multipart/form-data; charset=utf-8; boundary=0xKhTmLbOuNdArY
--0xKhTmLbOuNdArY
Content-Disposition: form-data; name="email"
myemailaddress#gmail.com
--0xKhTmLbOuNdArY
Content-Disposition: form-data; name="sqlite"; filename="backup.MyApp.v1.1.3-to-v1.1.3.1443578420.sqlite"
Content-Type: application/octet-stream
// ... data length: 880640
--0xKhTmLbOuNdArY--
Content-Disposition: form-data; name="sqliteshm"; filename="backup.MyApp.v1.1.3-to-v1.1.3.1443578420.sqlite-shm"
Content-Type: application/octet-stream
// ... data length: 32768
--0xKhTmLbOuNdArY--
Content-Disposition: form-data; name="sqlitewal"; filename="backup.MyApp.v1.1.3-to-v1.1.3.1443578420.sqlite-wal"
Content-Type: application/octet-stream
// ... data length: 3901672
--0xKhTmLbOuNdArY--
However, on the PHP side when I receive this post, I'm only seeing the first of the three files. If I put the one named "sqlite" first, then on the PHP side, I only see the "sqlite" file. If I put the one named "sqliteshm" first, then I only see the "sqliteshm" file in the $_FILES array.
array (
'sqliteshm' =>
array (
'name' => 'backup.MyApp.v1.1.3-to-v1.1.3.1443578420.sqlite-shm',
'type' => 'application/octet-stream',
'tmp_name' => '/private/var/tmp/phpk1wyWb',
'error' => 0,
'size' => 32768,
),
)
The file size matches up, regardless of which one I put first, but only the first file ever shows up on the PHP side.
Do I need to do something special in order to receive multiple files on the PHP side?
Or am I sending the multiple files incorrect from iOS?
In short, your request is not valid.
In more detail, notice the difference between --0xKhTmLbOuNdArY-- and --0xKhTmLbOuNdArY. The separator that uses two dashes at the end -- is a terminator. As a result, your request body isn't parsed beyond the first terminator, which happens to be the right after the first file. There should only be one terminator - at the very end of your request.
Generally, you shouldn't reinvent the wheel when it comes to composing multipart form data requests. Just use a proven and time tested library like AFNetworking.

HTTP PUT method in PHP: separating files from form data

When a file is uploaded via POST, the form data is separated out from the file(s) via the $_POST and $_FILES variables (respectively). On the other hand, when a file is uploaded via PUT, the response must be retrieved from a single source (php://input). Unfortunately, when a file is involved, php://input seems to contain multiple headers, which appear to be divided by a key of some kind (--6OJvloM5owOQsn2b3APr-Ad9dDLvRqBxm in this case).
--6OJvloM5owOQsn2b3APr-Ad9dDLvRqBxm
Content-Disposition: form-data; name="file"; filename="image.jpg"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
<<<BINARY DATA>>>
--6OJvloM5owOQsn2b3APr-Ad9dDLvRqBxm
Content-Disposition: form-data; name="description"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
<<<FILE DESCRIPTION>>>
--6OJvloM5owOQsn2b3APr-Ad9dDLvRqBxm--
Short of iterating over the entire response and trying to pick out the different headers, is there a way to separate the files from the form data?
Note: I'm using a well-known 3rd-party application to make the API requests, so it's unlikely that the problem resides in the requests themselves.
It seems that you are trying to do to much in one PUT request. However, if you really need to handle the raw data, you should be able to parse it as a MIME string using a library such as this one: http://pear.php.net/package/Mail_mimeDecode

PHPExcel: I need to create two workbooks on one submission [duplicate]

Use case: user clicks the link on a webpage - boom! load of files sitting in his folder.
I tried to pack files using multipart/mixed message, but it seems to work only for Firefox
This is how my response looks like:
HTTP/1.0 200 OK
Connection: close
Date: Wed, 24 Jun 2009 23:41:40 GMT
Content-Type: multipart/mixed;boundary=AMZ90RFX875LKMFasdf09DDFF3
Client-Date: Wed, 24 Jun 2009 23:41:40 GMT
Client-Peer: 127.0.0.1:3000
Client-Response-Num: 1
MIME-Version: 1.0
Status: 200
--AMZ90RFX875LKMFasdf09DDFF3
Content-type: image/jpeg
Content-transfer-encoding: binary
Content-disposition: attachment; filename="001.jpg"
<< here goes binary data >>--AMZ90RFX875LKMFasdf09DDFF3
Content-type: image/jpeg
Content-transfer-encoding: binary
Content-disposition: attachment; filename="002.jpg"
<< here goes binary data >>--AMZ90RFX875LKMFasdf09DDFF3
--AMZ90RFX875LKMFasdf09DDFF3--
Thank you
P.S. No, zipping files is not an option
Zipping is the only option that will have consistent result on all browsers. If it's not an option because you don't know zips can be generated dynamically, well, they can. If it's not an option because you have a grudge against zip files, well..
MIME/multipart is for email messages and/or POST transmission to the HTTP server. It was never intended to be received and parsed on the client side of a HTTP transaction. Some browsers do implement it, some others don't.
As another alternative, you could have a JavaScript script opening windows downloading the individual files. Or a Java Applet (requires Java Runtimes on the machines, if it's an enterprise application, that shouldn't be a problem [as the NetAdmin can deploy it on the workstations]) that would download the files in a directory of the user's choice.
Remember doing this >10 years ago in the netscape 4 days. It used boundaries like what your doing and didn't work at all with other browsers at that time.
While it does not answer your question HTTP 1.1 supports request pipelining so that at least the same TCP connection can be reused to download multiple images.
You can use base64 encoding to embed an (very small) image into a HTML document, however from a browser/server standpoint, you're technically still sending only 1 document. Maybe this is what you intend to do?
Embedd Images into HTML using Base64
EDIT: i just realized that most methods i found in my google search only support firefox, and not iE.
You could make a json with multiple data urls.
Eg:
{
"stamp.png": "data:image/png;base64,...",
"document.pdf": "data:application/pdf;base64,..."
}
(extending trinalbadger587's answer)
You could return an html with multiple clickable, downloadable, inplace data links:
<html>
<body>
<a download="yourCoolFilename.png" href="data:image/png;base64,...">PNG</a>
<a download="theFileGetsSavedWithThisName.pdf" href="data:application/pdf;base64,...">PDF</a>
</body>
</html>

Categories