Ok so ive already tried using connect-form and I couldnt get it working for some reason, but I figure I should understand how this works semi from scratch regardless.
I dont understand where the multipart/formdata file which I am uploaded is going, or how I can access it in my app when its posted to the url. -- Id like to access the file data directy, and write the file output using the node fs module. -- For instance:
app.post('/testy', function(req, res){
console.log(req.body);
console.log(req.headers);
res.redirect('back');
});
app.get('/testy', function(req, res){
res.send('<form method="post" action="/testy" enctype="multipart/form-data">'
+ '<p>Image: <input type="file" name="test" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
So the only req var that is actually being logged there is the req headers, body is empty. (probably supposed to be I understand that). But what I dont get is where is the file data? Looking for the php equiv of the $_FILES array I supposed. -- Here is my headers logged.
'accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-us,en;q=0.5',
'accept-encoding': 'gzip,deflate',
'accept-charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'keep-alive': '115',
connection: 'keep-alive',
referer: 'http://127.0.0.1:3000/testy',
cookie: 'connect.sid=lDRpluTxjUJeuTmkXlybrYeZ.JYTB155s2DGce2dsyfv1Op5ISCY8uqyqJZK8NjlZ5jM; socketio=flashsocket',
'x-insight': 'activate',
'content-type': 'multipart/form-data; boundary=---------------------------5856401949371863571646035001',
'content-length': '30128' }
Any light shed upon what Im missing as always much appreciated!
Here is very verbose version without connect-form. As you can see, this is not efficient but trying to be instructive about how it works.
var express = require('express'),
fs = require('fs');
app = express.createServer();
app.post('/testy', function(req, res){
var body = '';
var header = '';
var content_type = req.headers['content-type'];
var boundary = content_type.split('; ')[1].split('=')[1];
var content_length = parseInt(req.headers['content-length']);
var headerFlag = true;
var filename = 'dummy.bin';
var filenameRegexp = /filename="(.*)"/m;
console.log('content-type: ' + content_type);
console.log('boundary: ' + boundary);
console.log('content-length: ' + content_length);
req.on('data', function(raw) {
console.log('received data length: ' + raw.length);
var i = 0;
while (i < raw.length)
if (headerFlag) {
var chars = raw.slice(i, i+4).toString();
if (chars === '\r\n\r\n') {
headerFlag = false;
header = raw.slice(0, i+4).toString();
console.log('header length: ' + header.length);
console.log('header: ');
console.log(header);
i = i + 4;
// get the filename
var result = filenameRegexp.exec(header);
if (result[1]) {
filename = result[1];
}
console.log('filename: ' + filename);
console.log('header done');
}
else {
i += 1;
}
}
else {
// parsing body including footer
body += raw.toString('binary', i, raw.length);
i = raw.length;
console.log('actual file size: ' + body.length);
}
});
req.on('end', function() {
// removing footer '\r\n'--boundary--\r\n' = (boundary.length + 8)
body = body.slice(0, body.length - (boundary.length + 8))
console.log('final file size: ' + body.length);
fs.writeFileSync('files/' + filename, body, 'binary');
console.log('done');
res.redirect('back');
})
});
app.get('/testy', function(req, res){
res.send('<form method="post" action="/testy" enctype="multipart/form-data">'
+ '<p>Image: <input type="file" name="test" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.listen(4000);
How about running this snippet from the example library?
https://github.com/visionmedia/express/blob/master/examples/multipart/app.js
/**
* Module dependencies.
*/
var express = require('express')
, form = require('connect-form');
var app = express.createServer(
// connect-form (http://github.com/visionmedia/connect-form)
// middleware uses the formidable middleware to parse urlencoded
// and multipart form data
form({ keepExtensions: true })
);
app.get('/', function(req, res){
res.send('<form method="post" enctype="multipart/form-data">'
+ '<p>Image: <input type="file" name="image" /></p>'
+ '<p><input type="submit" value="Upload" /></p>'
+ '</form>');
});
app.post('/', function(req, res, next){
// connect-form adds the req.form object
// we can (optionally) define onComplete, passing
// the exception (if any) fields parsed, and files parsed
req.form.complete(function(err, fields, files){
if (err) {
next(err);
} else {
console.log('\nuploaded %s to %s'
, files.image.filename
, files.image.path);
res.redirect('back');
}
});
// We can add listeners for several form
// events such as "progress"
req.form.on('progress', function(bytesReceived, bytesExpected){
var percent = (bytesReceived / bytesExpected * 100) | 0;
process.stdout.write('Uploading: %' + percent + '\r');
});
});
app.listen(3000);
console.log('Express app started on port 3000');
npm install express
npm install connect-form
node app.js
works fine for me...
I was able to get the connect-form package working finally, rookie mistake but, if you are using express make sure you tell the app to use the form module within your config function app.configure(function(){
app.use(form({ keepExtensions: true }));
(the in the post it will be in the files.yourfileuploadfieldname.filename variable)
-- with that said Im still interested to know how to do it from scratch, without connect-form, if its not incredibly difficult to explain.
Related
I am using React Native to build Mobile application for Andrioid and iOS.
based on the situation that no framework is exist to support Azure Storage API for React Native (all frameworks are required browsers that does not exist in React Native),
I use REST API for the interaction with the Azure storage and it works fine e.g list containers, list blob, get blob and put blob.
in order to upload large file I tried to use the same mechanizm for 'put block' api (as describe here: https://learn.microsoft.com/en-us/rest/api/storageservices/put-block) without succcess, failed on error code 403.
I will appreciate for your assist.
Thank you.
my code for upload single block:
private createAuthorizationHeader(canonicalizedString: string) {
const str = CryptoJS.HmacSHA256(canonicalizedString, CryptoJS.enc.Base64.parse(this.config.accountKey));
const sig = CryptoJS.enc.Base64.stringify(str);
const authorizationHeader = `SharedKey ${this.config.accountName}:${sig}`;
return authorizationHeader;
}
async putBlockBlob(containerName: str, blobPath: str, blobContent: str, blockIndex: number,) {
const requestMethod = 'PUT';
const urlPath = `${containerName}/${blobPath}`;
const dateInRfc1123Format = new Date(Date.now()).toUTCString();
const storageServiceVersion = '2019-12-12';
const blobLength: number = blobContent.length;
const blockId = Buffer.from(`block-${blockIndex}`).toString('base64');
const blobType = 'BlockBlob';
// StringToSign =
// VERB + "\n" +
// Content-Encoding + "\n" +
// Content-Language + "\n" +
// Content-Length + "\n" +
// Content-MD5 + "\n" +
// Content-Type + "\n" +
// Date + "\n" +
// If-Modified-Since + "\n" +
// If-Match + "\n" +
// If-None-Match + "\n" +
// If-Unmodified-Since + "\n" +
// Range + "\n" +
// CanonicalizedHeaders +
// CanonicalizedResource;
const canonicalizedHeaders = `x-ms-date:${dateInRfc1123Format}\nx-ms-version:${storageServiceVersion}`;
const canonicalizedResource = `/${this.config.accountName}/${urlPath}}\nblockid:${blockId}\ncomp:block`;
const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;
const uriStr = `${urlPath}?comp=block&blockid=${blockId}`;
const authorizationHeader = this.createAuthorizationHeader(stringToSign);
const header = {
'cache-control': 'no-cache',
'x-ms-date': dateInRfc1123Format,
'x-ms-version': storageServiceVersion,
Authorization: authorizationHeader,
'Content-Length': `${blobLength}`,
'Content-Type': 'application/octet-stream',
};
try {
return axios
.create({baseURL: `https://${this.config.accountName}.blob.core.windows.net/`,})
.request({
method: requestMethod,
url: uriStr,
data: blobContent,
headers: header,
})
.then((response) => response.data)
.catch((err) => {
throw err;
});
} catch (err) {
console.log(err);
throw err;
}
}
I believe the issue is coming because of a missing new line character between Range and CanonicalizedHeaders.
Can you try by changing the following line of code:
const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;
to:
const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;
it will help you to upload the data to Azure storage server
upload file to Server
export const uploadMedia = async (params: any, callBack: any) => {
const SAS_URL: any = "https://${blobUrl}.blob.core.windows.net";
const CONTAINER: any = "";
const SAS_TOKEN: any = "";
const { fileType, localUri } = params;
const userId = "set user ID here";
const fileName = String(fileType).concat(customIdGenerator(7));
const assetPath = `${SAS_URL}/${CONTAINER}/${userId}/${fileName}`;
HEADER["x-ms-blob-content-type"] = CONST_HEADER(fileType);
return await RNFetchBlob.fetch(
"PUT",
`${assetPath}?${SAS_TOKEN}`,
HEADER,
RNFetchBlob.wrap(localUri)
)
?.uploadProgress(callBack)
.then(() => {
return assetPath;
});
};
fileType = 'video' | image | pdf
let params: any = {
fileType: 'image',
localUri: image,
};
generate Custom Id for Uniqueness or you can also use UUID
const customIdGenerator = (length: any) => {
var result = "";
var characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
};
set Headers for different Files
const CONST_HEADER = (type: any) => {
return type == 'image'
? `image/png`
: type == 'video'
? 'video/mp4'
: type == 'pdf' && 'application/pdf';
};
*FrontEnd
As you can see in the code. I'm trying to make a Chat Application. The Message I'm sending is triggered and my Event is being Processed. But the problem is I'm not able to catch message from receiver side. I'm a stage Beginner developer and making application via youtube tutorials. Thankyou...
<script>
$(function (){
let $chatInput = $(".chat-input");
let $chatInputToolbar = $(".chat-input-toolbar");
let $chatBody = $(".chat-body");
let $messageWrapper = $("#messageWrapper");
let user_id = "{{ auth()->user()->id }}";
let ip_address = 'http://127.0.0.1';
let socket_port = '8005';
let socket = io(ip_address + ':' + socket_port);
let friendId = "{{ $friendInfo->id }}";
socket.on('connect', function() {
socket.emit('user_connected', user_id);
});
socket.on('updateUserStatus', (data) => {
let $userStatusIcon = $('.user-status-icon ');
$userStatusIcon.removeClass('text-success');
$userStatusIcon.attr('title', 'Away');
$.each(data, function (key, val) {
if (val !== null && val !== 0) {
let $userIcon = $(".user-icon-"+key);
$userIcon.addClass('text-success');
$userIcon.attr('title','Online');
}
});
});
$chatInput.keypress(function (e) {
let message = $(this).html(); //text
if (e.which === 13 && !e.shiftKey) {
$chatInput.html("");
sendMessage(message);
return false;
}
});
function sendMessage(message) {
let url = "{{ route('message.send-message') }}";
let form = $(this);
let formData = new FormData();
let token = "{{ csrf_token() }}";
formData.append('message', message);
formData.append('_token', token);
formData.append('receiver_id', friendId);
appendMessageToSender(message);
$.ajax({
url: url,
type: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'JSON',
success: function (response) {
if (response.success) {
console.log(response.data);
}
}
});
}
function appendMessageToSender(message) {
let name = '{{ $myInfo->name }}';
let image = '{!! makeImageFromName($myInfo->name) !!}';
let userInfo = '<div class="col-md-12 user-info">\n' +
'<div class="chat-image">\n' + image +
'</div>\n' +
'\n' +
'<div class="chat-name font-weight-bold">\n' +
name +
'<span class="small time text-gray-500"
title="'+getCurrentDateTime()+'">\n' +
getCurrentTime()+'</span>\n' +
'</div>\n' +
'</div>\n';
let messageContent = '<div class="col-md-12 message-content">\n' +
'<div class="message-text">\n' +
message +
'</div>\n' +
'</div>';
let newMessage = '<div class="row message align-item-center mb-2">'
+userInfo + messageContent +
'</div>';
$messageWrapper.append(newMessage);
}
function appendMessageToReceiver(message) {
let name = '{{ $friendInfo->name }}';
let image = '{!! makeImageFromName($friendInfo->name) !!}';
let userInfo = '<div class="col-md-12 user-info">\n' +
'<div class="chat-image">\n' + image +
'</div>\n' +
'\n' +
'<div class="chat-name font-weight-bold">\n' +
name +
'<span class="small time text-gray-500"
title="'+dateFormat(message.created_at)+'">\n' +
timeFormat(message.created_at)+'</span>\n' +
'</div>\n' +
'</div>\n';
let messageContent = '<div class="col-md-12 message-content">\n' +
'<div class="message-text">\n' + message.content +
'</div>\n' +
'</div>';
let newMessage = '<div class="row message align-items-center mb-2">'
+userInfo + messageContent +
'</div>';
$messageWrapper.append(newMessage);
}
{
appendMessageToReceiver(message);
});
I think I'm missing something in the socket.on function:
socket.on("private-channel:App\Events\PrivateMessageEvent", function (message)
socket.on("private-channel:App\\Events\\PrivateMessageEvent", function (message)
{
appendMessageToReceiver(message);
});
});
BackEnd Server
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http, {
cors: {
origin: "*",
}
});
var Redis = require('ioredis');
var redis = new Redis();
var users = [];
http.listen(8005, function() {
console.log('Listening to port 8005');
});
redis.subscribe('private-channel', function() {
console.log('subscribed to private channel');
});
redis.on('message', function(channel, message) {
message = JSON.parse(message);
console.log(message);
if (channel == 'private-channel') {
let data = message.data.data;
let receiver_id = data.receiver_id;
let event = message.event;
io.to('${users[receiver_id]}').emit(channel + ':' + event, data);
}
});
io.on('connection', function (socket) {
socket.on("user_connected", function (user_id) {
users[user_id] = socket.id;
io.emit('updateUserStatus', users);
console.log("user connected "+ user_id);
});
socket.on('disconnect', function() {
var i = users.indexOf(socket.id);
users.splice(i, 1, 0);
io.emit('updateUserStatus', users);
console.log('users');
});
});
PrivateMessageEvent
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class PrivateMessageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
Public $data;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('private-channel');
}
.env
Here's is my .env file.
APP_NAME=chat_application
APP_ENV=local
//App_key
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=chat_application
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=redis
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=database
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}
"
I've noticed one issue in the event emitting in your server side code, here is the code which emits the socket events
io.to('${users[receiver_id]}').emit(channel + ':' + event, data);
So, you trying to use string interpolation and above syntax is incorrect. Basically, this is just a string '${users[receiver_id]}'. This need to be changed to `${users[receiver_id]}`, and below is the updated code
io.to(`${users[receiver_id]}`).emit(channel + ':' + event, data);
So, when using string interpolation you need to use back ticks instead of single quotes.
And another point is make sure, your channel + ':' + event in io.to('${users[receiver_id]}').emit(channel + ':' + event, data); is same as the client event in your client side code - "private-channel:App\\Events\\PrivateMessageEvent",
socket.on("private-channel:App\\Events\\PrivateMessageEvent", function (message) {
appendMessageToReceiver(message);
});
I am trying to upload a photo from JavaScript using the StreetView Publish API and it seems that everything i try fails ... currently i have the uploadUrl and i need to make a post request with the actual image data
this is that i ended up doing
var input = document.querySelector('input[type="file"]').files;
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var xhr = new XMLHttpRequest();
xhr.open("POST", window.uploadUrl, true);
xhr.setRequestHeader("Authorization", gapi.client.getToken().token_type + ' ' + gapi.client.getToken().access_token);
xhr.setRequestHeader("Content-Type", "image/jpeg");
xhr.setRequestHeader("X-Goog-Upload-Protocol", "raw");
xhr.setRequestHeader("X-Goog-Upload-Content-Length", dataURL.length );
xhr.onreadystatechange = function() {//Call a function when the state changes.
if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
console.log(xhr);
}
}
xhr.send(dataURL);
};
reader.readAsDataURL(input[0]);
the answer i get is the following one:
Failed to load
https://streetviewpublish.googleapis.com/media/user/.../photo/...:
Response for preflight is invalid (redirect)
can anyone suggest any possible solution to this?
thanks
UPDATE
from what i see ... when i am trying to upload the image, 2 requests are generated ... both are OPTIONS and 302 status and none of them have the headers i am trying to send ... mainly the access token
var xhr = new XMLHttpRequest();
xhr.open("POST", window.uploadUrl + "?key=...", true);
xhr.setRequestHeader("Authorization", gapi.client.getToken().token_type + ' ' + gapi.client.getToken().access_token);
xhr.setRequestHeader("Authorization", gapi.client.getToken().access_token);
xhr.setRequestHeader("Content-Type", 'image/jpeg');
xhr.setRequestHeader("X-Goog-Upload-Protocol", "raw");
xhr.setRequestHeader("X-Goog-Upload-Content-Length", dataURL.length );
xhr.onreadystatechange = function() {
if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
console.log(xhr);
}
}
xhr.send(dataURL);
When trying to read data in Node.js from an ImageMagick child process, it comes out corrupted.
A simple test case would be the following:
var fs = require('fs');
var exec = require('child_process').exec;
var cmd = 'convert ./test.jpg -';
exec(cmd, {encoding: 'binary', maxBuffer: 5000*1024}, function(error, stdout) {
fs.writeFileSync('test2.jpg', stdout);
});
I would expect that to be the equivalent of the command line convert ./test.jpg - > test2.jpg that does write the binary file correctly.
Originally there was a problem with the maxBuffer option being too small and resulting in a truncated file. After increasing that, the file now appears slightly larger than expected and still corrupted.
The data from stdout is required to send over HTTP.
What would be the correct way to read this data from the ImageMagick stdout?
There were two problems with the initial approach.
The maxBuffer needs to be high enough to handle the whole response from the child process.
Binary encoding needs to be properly set everywhere.
A full working example would be the following:
var fs = require('fs');
var exec = require('child_process').exec;
var cmd = 'convert ./test.jpg -';
exec(cmd, {encoding: 'binary', maxBuffer: 5000*1024}, function(error, stdout) {
fs.writeFileSync('test2.jpg', stdout, 'binary');
});
Another example, sending the data in an HTTP response using the Express web framework, would like this:
var express = require('express');
var app = express.createServer();
app.get('/myfile', function(req, res) {
var cmd = 'convert ./test.jpg -';
exec(cmd, {encoding: 'binary', maxBuffer: 5000*1024}, function(error, stdout) {
res.send(new Buffer(stdout, 'binary'));
});
});
Ah, problem is:
If timeout is greater than 0, then it
will kill the child process if it runs
longer than timeout milliseconds. The
child process is killed with
killSignal (default: 'SIGTERM').
maxBuffer specifies the largest amount
of data allowed on stdout or stderr -
if this value is exceeded then the
child process is killed.
Source: http://nodejs.org/docs/v0.4.8/api/child_processes.html#child_process.exec
So if your image is over the default buffer size of 200*1024 bytes, your image is going to be corrupted as you mentioned. I was able to get it to work with the following code:
var fs = require('fs');
var spawn = require('child_process').spawn;
var util = require('util');
var output_file = fs.createWriteStream('test2.jpg', {encoding: 'binary'});
var convert = spawn('convert', ['test.jpg', '-']);
convert.stdout.on('data', function(data) {
output_file.write(data);
});
convert.on('exit', function(code) {
output_file.end();
});
Here I used spawn to get a streamable stdout, then I used a Writeable Stream to write the data in binary format. Just tested it and was able to open the resulting test2.jpg image.
EDIT: Yes you can use this to send the result over HTTP. Here's an example of me downsizing an image with convert, then posting the result to the glowfoto API:
var fs = require('fs');
var http = require('http');
var util = require('util');
var spawn = require('child_process').spawn;
var url = require('url');
// Technically the only reason I'm using this
// is to get the XML parsed from the first call
// you probably don't need this, but just in case:
//
// npm install xml2js
var xml = require('xml2js');
var post_url;
var input_filename = 'giant_image.jpg';
var output_filename = 'giant_image2.jpg';
// The general format of a multipart/form-data part looks something like:
// --[boundary]\r\n
// Content-Disposition: form-data; name="fieldname"\r\n
// \r\n
// field value
function EncodeFieldPart(boundary,name,value) {
var return_part = "--" + boundary + "\r\n";
return_part += "Content-Disposition: form-data; name=\"" + name + "\"\r\n\r\n";
return_part += value + "\r\n";
return return_part;
}
// Same as EncodeFieldPart except that it adds a filename,
// as well as sets the content type (mime) for the part
function EncodeFilePart(boundary,type,name,filename) {
var return_part = "--" + boundary + "\r\n";
return_part += "Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + filename + "\"\r\n";
return_part += "Content-Type: " + type + "\r\n\r\n";
return return_part;
}
// We could use Transfer-Encoding: Chunked in the headers
// but not every server supports this. Instead we're going
// to build our post data, then create a buffer from it to
// pass to our MakePost() function. This means you'll have
// 2 copies of the post data sitting around
function PreparePost() {
// Just a random string I copied from a packet sniff of a mozilla post
// This can be anything you want really
var boundary = "---------------------------168072824752491622650073";
var post_data = '';
post_data += EncodeFieldPart(boundary, 'type', 'file');
post_data += EncodeFieldPart(boundary, 'thumbnail', '400');
post_data += EncodeFilePart(boundary, 'image/jpeg', 'image', output_filename);
fs.readFile(output_filename, 'binary', function(err,data){
post_data += data;
// This terminates our multi-part data
post_data += "\r\n--" + boundary + "--";
// We need to have our network transfer in binary
// Buffer is a global object
MakePost(new Buffer(post_data, 'binary'));
});
}
function MakePost(post_data) {
var parsed_url = url.parse(post_url);
var post_options = {
host: parsed_url.hostname,
port: '80',
path: parsed_url.pathname,
method: 'POST',
headers : {
'Content-Type' : 'multipart/form-data; boundary=---------------------------168072824752491622650073',
'Content-Length' : post_data.length
}
};
var post_request = http.request(post_options, function(response){
response.setEncoding('utf8');
response.on('data', function(chunk){
console.log(chunk);
});
});
post_request.write(post_data);
post_request.end();
}
// Glowfoto first makes you get the url of the server
// to upload
function GetServerURL() {
var response = '';
var post_options = {
host: 'www.glowfoto.com',
port: '80',
path: '/getserverxml.php'
};
var post_req = http.request(post_options, function(res) {
res.setEncoding('utf8');
// Here we buildup the xml
res.on('data', function (chunk) {
response += chunk;
});
// When we're done, we parse the xml
// Could probably just do string manipulation instead,
// but just to be safe
res.on('end', function(){
var parser = new xml.Parser();
parser.addListener('end', function(result){
// Grab the uploadform element value and prepare our post
post_url = result.uploadform;
PreparePost();
});
// This parses an XML string into a JS object
var xml_object = parser.parseString(response);
});
});
post_req.end();
}
// We use spawn here to get a streaming stdout
// This will use imagemagick to downsize the full image to 30%
var convert = spawn('convert', ['-resize', '30%', input_filename, '-']);
// Create a binary write stream for the resulting file
var output_file = fs.createWriteStream(output_filename, {encoding: 'binary'});
// This just writes to the file and builds the data
convert.stdout.on('data', function(data){
output_file.write(data);
});
// When the process is done, we close off the file stream
// Then trigger off our POST code
convert.on('exit', function(code){
output_file.end();
GetServerURL();
});
Sample result:
$ node test.js
<?xml version="1.0" encoding="utf-8"?>
<upload>
<thumburl>http://img4.glowfoto.com/images/2011/05/29-0939312591T.jpg</thumburl>
<imageurl>http://www.glowfoto.com/static_image/29-093931L/2591/jpg/05/2011/img4/glowfoto</imageurl>
<codes>http://www.glowfoto.com/getcode.php?srv=img4&img=29-093931L&t=jpg&rand=2591&m=05&y=2011</codes>
</upload>
You can also take advantage of io pipes in nodejs
var file = fs.createWritableStream("path-to-file", {encoding: 'binary'});
converter = spawn(cmd, ['parameters ommited']);
converter.stdout.pipe(file); //this will set out stdout.write cal to you file
converter.on('exit', function(){ file.end();});
i want to upload a file by node.js so i try by this article.
http://debuggable.com/posts/parsing-file-uploads-at-500-mb-s-with-node-js:4c03862e-351c-4faa-bb67-4365cbdd56cb
I run this code
var formidable = require('formidable')
, http = require('http')
, sys = require('sys');
var server=http.createServer(function(req, res) {
console.log('out if condition'+sys.inspect(req));
if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
// parse a file upload
console.log('in if condition');
var form = new formidable.IncomingForm();
form.parse(req, function(fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(sys.inspect({fields: fields, files: files}));
});
return;
}
// show a file upload form
res.writeHead(200, {'content-type': 'text/html'});
res.end
( '<form action="/upload" enctype="multipart/form-data" method="post">'
+ '<input type="text" name="title"><br>'
+ '<input type="file" name="upload" multiple="multiple"><br>'
+ '<input type="submit" value="Upload">'
+ '</form>'
);
});
server.listen(8000);
when i upload the file it doesn't proceed further easily and doesn't go in if condition of upload why ?
fs.writeFile(files.upload.name, files.upload,'utf8', function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
Please check.
http://rahulmehta1.wordpress.com/2011/04/26/uploading-a-file-in-node-js-by-formidable/